home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / telecomm / sticpsrc.lzh / SOURCE.ARC / PERSIST.C < prev    next >
C/C++ Source or Header  |  1990-05-02  |  4KB  |  177 lines

  1. /* automatic persistence setting for ax.25 interfaces */
  2.  
  3. #include "global.h"
  4. #include "ax25.h"
  5. #include "iface.h"
  6. #include "persist.h"
  7. #include "timer.h"
  8.  
  9. static struct persist *pblk;        /* list of persistence cb's */
  10. static struct timer p_timer;
  11. static void tick_ptimer();
  12. extern char nospace[],notax25[];
  13.  
  14. /* set/show automatic persistence calculation parameters */
  15. int
  16. dopersist(argc,argv)
  17. int argc;
  18. char *argv[];
  19. {
  20.     register struct persist *pp;
  21.     struct interface *ifp;
  22.  
  23.     if (argc == 1){            /* no args - show parms */
  24.         printf("IF    Users    P   P0  Pmin  Pmax  Tinc  Tmax\n");
  25.  
  26.         for (pp = pblk; pp != NULLPERSIST; pp = pp->next)
  27.         printf("%-6s%5d%5d%5d%6d%6d%6d%6d\n",pp->iface->name,
  28.             pp->n_users,pp->p,pp->p0,pp->p_min,pp->p_max,
  29.             pp->pt_incr * PT_INTER,pp->pt_max * PT_INTER);
  30.  
  31.         return 0;
  32.     }
  33.  
  34.     if ((ifp = ifunit(argv[1])) == NULLIF)
  35.         return 1;
  36.  
  37.     if (!(ifp->flags & IF_AX25)){
  38.         printf(notax25,argv[1]);
  39.         return 1;
  40.     }
  41.  
  42.     stop_timer(&p_timer);
  43.  
  44.     for (pp = pblk; pp != NULLPERSIST; pp = pp->next)
  45.         if (pp->iface == ifp)    /* lookup by interface */
  46.         break;
  47.  
  48.     if (pp == NULLPERSIST){        /* if not in list? */
  49.         if ((pp = (struct persist *) calloc(1,sizeof(struct persist))) == NULLPERSIST){
  50.         printf(nospace);
  51.         if (pblk != NULLPERSIST)
  52.             start_timer(&p_timer);
  53.         return 1;
  54.         }
  55.  
  56.         if ((pp->next = pblk) != NULLPERSIST)
  57.         pp->next->prev = pp;
  58.  
  59.         pblk = pp;
  60.         pp->iface = ifp;
  61.         pp->p0 = P0;
  62.         pp->p_min = P_MIN;
  63.         pp->p_max = pp->p = P_MAX;
  64.         pp->pt_incr = PT_INCR;
  65.         pp->pt_max = PT_MAX;
  66.     }
  67.  
  68.     /* set control values, delete cb when p0 value is 0 (or "off") */
  69.  
  70.     if (argc > 2)
  71.         if ((pp->p0 = atoi(argv[2])) == 0){
  72.         if (pp->prev != NULLPERSIST)
  73.             pp->prev->next = pp->next;
  74.         else
  75.             pblk = pp->next;
  76.  
  77.         if (pp->next != NULLPERSIST)
  78.             pp->next->prev = pp->prev;
  79.  
  80.         free(pp);
  81.         }
  82.  
  83.     if (argc > 3)
  84.         pp->p_min = atoi(argv[3]);
  85.  
  86.     if (argc > 4)
  87.         pp->p_max = atoi(argv[4]);
  88.  
  89.     if (argc > 5)
  90.         pp->pt_incr = atoi(argv[5]) / PT_INTER;
  91.  
  92.     if (argc > 6)
  93.         pp->pt_max = atoi(argv[6]) / PT_INTER;
  94.  
  95.     /* (re)start the timer only if any persistence cb's left */
  96.  
  97.     if (pblk != NULLPERSIST){
  98.         p_timer.start = SEC2TICK(PT_INTER);
  99.         p_timer.func = tick_ptimer;
  100.         tick_ptimer();
  101.     }
  102.     return 0;
  103. }
  104.  
  105. /* update the "number of users" for an interface when a callsign is heard */
  106. /* the ssid is not considered significant */
  107.  
  108. int
  109. upd_nusers (ifp,call)
  110. struct interface *ifp;
  111. register unsigned char *call;
  112.  
  113. {
  114.     register struct persist *pp;
  115.     register unsigned hashval;
  116.     register int i;
  117.  
  118.     for (pp = pblk; pp != NULLPERSIST; pp = pp->next)
  119.         if (pp->iface == ifp)    /* lookup by interface */
  120.         break;
  121.  
  122.     if (pp == NULLPERSIST)        /* if not in list? */
  123.         return -1;            /* return soft failure */
  124.  
  125.     hashval = 0;
  126.     for (i = 0; i < ALEN; i++)    /* scan callsign (not SSID) */
  127.         hashval = (hashval << 1) ^ (*call++ & 0xfe);
  128.  
  129.     hashval %= (unsigned) SLOTS;
  130.  
  131.     if ((pp->heard[hashval] += pp->pt_incr) > pp->pt_max)
  132.         pp->heard[hashval] = pp->pt_max;
  133.  
  134.     return 0;            /* ok */
  135. }
  136.  
  137. /* tick the "automatic persistence" timer, decrementing the timers and */
  138. /* re-computing the number of users on each channel.  when changed, set */
  139. /* the persistence value for that channel. */
  140.  
  141. static void
  142. tick_ptimer ()
  143.  
  144. {
  145.     register struct persist *pp;
  146.     register unsigned i,n_users,p;
  147.     static char *argv[3] = {"2","###",NULLCHAR};
  148.  
  149.     for (pp = pblk; pp != NULLPERSIST; pp = pp->next){
  150.         n_users = 0;
  151.         for (i = 0; i < SLOTS; i++)
  152.         if (pp->heard[i]){
  153.             pp->heard[i]--;
  154.             n_users++;        /* count the active users */
  155.         }
  156.  
  157.         if ((pp->n_users = n_users) == 0)
  158.         p = pp->p0;
  159.         else
  160.         p = pp->p0 / n_users;
  161.  
  162.         if (p > pp->p_max)        /* keep p within p_min .. p_max */
  163.         p = pp->p_max;
  164.  
  165.         if (p < pp->p_min)
  166.         p = pp->p_min;
  167.  
  168.         if (pp->p != p){        /* a change in p value? */
  169.         sprintf(argv[1],"%d",pp->p = p); /* convert to string */
  170.         if (pp->iface->ioctl != NULLFP)
  171.            (*pp->iface->ioctl)(pp->iface,2,argv); /* set p value */
  172.         }
  173.     }
  174.  
  175.     start_timer(&p_timer);        /* restart the timer */
  176. }
  177.